package com.capinfo.commons.project.model.security;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OrderBy;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.Where;

import com.capinfo.components.security.model.SecureRole;
import com.capinfo.framework.model.MultipleEntity;
import com.capinfo.framework.model.StatusEnabled;

/**
 * <p>
 * 角色: 关联用户与资源关系的角色。
 * </p>
 * 
 */
@Entity
@Table(name = "SYSTEM_ROLES")
@SequenceGenerator(name = "seqRoles", sequenceName = "SEQ_ROLES", allocationSize = 1)
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class SystemRole implements StatusEnabled,
		SecureRole<SystemRole, SystemUser, SystemResource, SystemViewStamp> {

	// ID
	private Long id;

	// 名称
	private String name;

	// 角色的描述
	private String description;

	// 是否可用 1-可用 0-不可用
	private Boolean enabled = Boolean.TRUE;

	// 资源
	private Set<SystemResource> resources = new HashSet<SystemResource>();

	// 用户
	private Set<SystemUser> users = new HashSet<SystemUser>();
	// 视图标记
	private Set<SystemViewStamp> viewStamps = new HashSet<SystemViewStamp>();

	public SystemRole() {
	}

	@Id
	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seqRoles")
	@Column(name = "ID", unique = true, nullable = false, precision = 10, scale = 0)
	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	@Column(name = "ROLE_NAME", length = 30)
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Column(name = "DESCRIPTION", length = 1500)
	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	@Column(name = "ENABLED", precision = 1, scale = 0)
	public Boolean getEnabled() {
		return enabled;
	}

	public void setEnabled(Boolean enabled) {
		this.enabled = enabled;
	}

	@ManyToMany(targetEntity = SystemResource.class, cascade = CascadeType.REFRESH, fetch = FetchType.LAZY)
	@Fetch(FetchMode.SUBSELECT)
	@JoinTable(name = "SYSTEM_RESOURCES_ROLES", joinColumns = { @JoinColumn(name = "ROLE_ID") }, inverseJoinColumns = { @JoinColumn(name = "RESOURCE_ID") })
	@OrderBy(value = "parentId asc")
	public Set<SystemResource> getResources() {
		return resources;
	}

	public void setResources(Set<SystemResource> resources) {
		this.resources = resources;
	}

	@ManyToMany(targetEntity = SystemUser.class, cascade = CascadeType.REFRESH, fetch = FetchType.LAZY, mappedBy = "roles")
	public Set<SystemUser> getUsers() {
		return users;
	}

	public void setUsers(Set<SystemUser> users) {
		this.users = users;
	}
	
	/**
	 * 视图标记
	 */
	@ManyToMany(targetEntity=SystemViewStamp.class, cascade=CascadeType.ALL , fetch=FetchType.LAZY)
	@Fetch(FetchMode.SUBSELECT)
	@JoinTable(name="SYSTEM_ROLES_VIEWSTAMPS", joinColumns={@JoinColumn(name="ROLE_ID")}, inverseJoinColumns={@JoinColumn(name="VIEW_STAMP_ID")})
	@OrderBy(value = "id asc")
	@Where( clause = "ENABLED = 1")
	public Set<SystemViewStamp> getViewStamps() {
		return viewStamps;
	}

	public void setViewStamps(Set<SystemViewStamp> viewStamps) {
		this.viewStamps = viewStamps;
	}

	@Transient
	public MultipleEntity getViewTokens() {
		return null;
	}

	public boolean equals(Object other) {
		if ((this == other))
			return true;
		if (!(other instanceof SystemRole))
			return false;
		SystemRole castOther = (SystemRole) other;
		return new EqualsBuilder().append(this.getId(), castOther.getId())
		// .append(this.getName(), castOther.getName())
				.isEquals();
	}

	public int hashCode() {
		return new HashCodeBuilder().append(getId())
		// .append(getName())
				.toHashCode();
	}

	@Override
	public String toString() {
		
		return new ToStringBuilder(this).append("id" , getId())
										.append("name" ,this.getName())
										.append("description",this.getDescription())
										.append("viewStamps",this.getViewStamps()).toString(); 
	}
}